﻿@page "/View/{ContactId:int}"

@using Microsoft.EntityFrameworkCore

@inject IDbContextFactory<ContactContext> DbFactory
@inject IPageHelper PageHelper
@inject EditSuccess EditSuccessState

@if (NotFound && !Loading)
{
    <div class="alert alert-warning">A contact with that id doesn't exist.</div>
}
else
{
    @if (Contact is null || Loading)
    {
        <div class="alert alert-info">Loading...</div>
    }
    else
    {
        <h1>@Contact.LastName, @Contact.FirstName</h1>
        <br />
        @if (EditSuccess)
        {
            <div class="alert alert-success">Successfully updated the contact.</div>
        }
        <hr />
        <h2>📞 Phone</h2>
        <br />
        <h3>@Contact.Phone</h3>
        <br />
        <h2>🏠 Address</h2>
        <br />
        <h3>@Contact.Street</h3>
        <h3>@Contact.City, @Contact.State @Contact.ZipCode</h3>
        <br />
        <a class="btn btn-primary" title="Go Back" href="@PageHelper.Page">
            🔙 Back to Grid
        </a>
        @if (!Deleted)
        {
            <a class="btn btn-primary" href="edit/@Contact.Id" title="Edit">Edit</a><span>&nbsp;</span>
            @if (!ShowConfirmation)
            {
                <button class="btn btn-danger" @onclick="@(() => { ShowConfirmation = true; EditSuccess = false; })">Delete</button>
            }
            else
            {
                <br />
                <br />
                <DeletePrompt Confirmation="@(async result => await ConfirmAsync(result))" />
            }
        }
        else
        {
            <div class="btn btn-danger">🚫 This item has been deleted.</div>
        }
    }
}

@code {
    /// <summary>
    /// Tracking of asynchronous calls.
    /// </summary>
    private bool Loading;

    /// <summary>
    /// Id from route of contact.
    /// </summary>
    [Parameter]
    public int ContactId { get; set; }

    /// <summary>
    /// Navigation check.
    /// </summary>
    private int _lastContactId;

    /// <summary>
    /// True with redirect from successful edit.
    /// </summary>
    [Parameter]
    public bool EditSuccess { get; set; }

    /// <summary>
    /// Contact entity.
    /// </summary>
    private Contact? Contact { get; set; }

    /// <summary>
    /// Set to true when not found.
    /// </summary>
    private bool NotFound = false;

    /// <summary>
    /// Set to true when delete is requested.
    /// </summary>
    private bool ShowConfirmation = false;

    /// <summary>
    /// Set to true when delete is successful
    /// </summary>
    private bool Deleted = false;

    /// <summary>
    /// Navigated
    /// </summary>
    /// <returns>Task</returns>
    protected override async Task OnParametersSetAsync()
    {
        if (_lastContactId != ContactId)
        {
            EditSuccess = EditSuccessState.Success;
            EditSuccessState.Success = false;
            _lastContactId = ContactId;
            await LoadContactAsync();
        }
        await base.OnParametersSetAsync();
    }

    /// <summary>
    /// Confirm deletion
    /// </summary>
    /// <param name="result">True when user confirmed</param>
    /// <returns>Task</returns>
    private async Task ConfirmAsync(bool result)
    {
        if (result)
        {
            await DeleteAsync();
        }
        else
        {
            ShowConfirmation = false;
            EditSuccess = false;
        }
    }

    /// <summary>
    /// Loads the contact
    /// </summary>
    /// <returns>Task</returns>
    private async Task LoadContactAsync()
    {
        if (Loading)
        {
            return; //avoid concurrent requests
        }

        NotFound = false;
        Contact = null;

        Loading = true;

        using var context = DbFactory.CreateDbContext();

        if (context.Contacts is not null)
        {
            Contact = await context.Contacts
                .AsNoTracking()
                .SingleOrDefaultAsync(
                    c => c.Id == ContactId);

            if (Contact is null)
            {
                NotFound = true;
            }
        }

        Loading = false;
    }

    /// <summary>
    /// Deletes the contact.
    /// </summary>
    /// <returns>Task</returns>
    private async Task DeleteAsync()
    {
        if (Loading)
        {
            return; // avoid concurrent requests
        }

        Loading = true;
        using var context = DbFactory?.CreateDbContext();

        if (context?.Contacts is not null)
        {
            var contact = await context.Contacts
                .SingleOrDefaultAsync(c => c.Id == ContactId);

            if (contact is not null)
            {
                context.Contacts?.Remove(contact);
                await context.SaveChangesAsync();
                Loading = false;
                Deleted = true;
            }
            else
            {
                Loading = false;
                // show not found
                await LoadContactAsync();
            }
        }
        else
        {
            Loading = false;
            // show not found
            await LoadContactAsync();
        }
    }
}
